Skip to content

feat(cli): add --fail-on CI/CD gate, --help/--version, robust arg parsing#5

Open
dmchaledev wants to merge 1 commit into
mainfrom
claude/magical-ptolemy-qGJsN
Open

feat(cli): add --fail-on CI/CD gate, --help/--version, robust arg parsing#5
dmchaledev wants to merge 1 commit into
mainfrom
claude/magical-ptolemy-qGJsN

Conversation

@dmchaledev
Copy link
Copy Markdown
Contributor

Why

The README markets sbom-diff as "perfect for CI/CD gates and audit trails," but the CLI always exited 0 regardless of what the diff found. That means it could not actually gate anything — a pipeline had no way to fail a build when a new critical CVE or a major-version bump was introduced. This PR delivers that keystone capability.

What changed

  • --fail-on <conditions> — exit non-zero when the diff matches one or more comma-separated conditions:
    • any, added, removed, upgraded, major, new-cves
    • CVE severity thresholds: low / medium / high / critical (fires on any new CVE at or above that level)
    • On failure, prints a clear reason, e.g. Gate failed (--fail-on critical,major): 1 new CVE(s) at or above critical severity; 1 major version bump(s).
  • The gate is implemented as a pure, tested evaluateGate(report, conditions) helper (plus parseGateConditions), now exported from the public API for programmatic use.
  • --help and --version flags.
  • Input validation for --format and --fail-on with actionable error messages instead of a silent cast / generic throw.
  • Fixed a latent arg-parsing bug: flag values placed before the file paths (e.g. --format markdown old.json new.json) were previously misread as positional file arguments. Positional collection now skips value flags and their consumed tokens.

Usage

# Fail the pipeline if a new critical CVE or a major version bump appears
npx @hailbytes/sbom-diff old.json new.json --fail-on critical,major
import { parse, diff, evaluateGate } from '@hailbytes/sbom-diff';

const report = diff(parse(oldJSON), parse(newJSON));
const gate = evaluateGate(report, ['critical', 'major']);
if (gate.shouldFail) throw new Error(`SBOM gate failed: ${gate.reasons.join('; ')}`);

Testing

  • Added src/__tests__/gate.test.ts (13 cases covering parsing, severity thresholds, major-bump detection, multi-condition reasons, and unknown-severity handling).
  • Full suite: 33 tests pass (was 20). lint, typecheck, and build all clean.
  • End-to-end CLI smoke-tested: correct exit codes for clean diffs (0), triggered gates (1), invalid conditions/formats (1), and flags placed before file paths.

No dependency or runtime-behavior changes for existing invocations — --fail-on is opt-in and the default output path is unchanged.

https://claude.ai/code/session_01YSnNaUitHirz9vbcjQQCjC


Generated by Claude Code

The README markets sbom-diff as "perfect for CI/CD gates," but the CLI
always exited 0, so it could not actually fail a build. This adds a
--fail-on flag that exits non-zero when the diff matches one or more
conditions (any/added/removed/upgraded/major/new-cves or a CVE severity
threshold), implemented as a pure, tested evaluateGate() helper that is
also exported from the public API.

Also:
- Add --help and --version flags.
- Validate --format and --fail-on values with clear error messages.
- Fix latent arg parsing so value flags before the file paths no longer
  get misread as positional file arguments.
- Add 13 gate tests and document the feature in the README.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants